%==========================================================================
%=  This file is part of the Sound Restoration Project
%=  (c) Copyright Interdisciplinary Mathematics Institute
%=                University of South Carolina, Department of Mathematics
%=  ALL RIGHTS RESERVED
%=
%=  Author: Borislav Karaivanov
%==========================================================================

%==========================================================================
% List of the files on which this procedure depends:
%
% none
%
%==========================================================================

%==========================================================================
% The function "getFileSequenceFromRepresetative" takes the name (including
% a full directory path) of a single file and finds all files residing in
% the same directory whose names have the same prefix and extension but a
% different index. Among them only those with indices within a specified
% range are identified.
% INPUT: "inFileName" is a string specifying a file name (including a full
% directory path).
% "firstFileInd" and "lastFileInd" are optional, non-negative integers
% specifying a range of indices outside of which files do not need to be
% considered.
% OUTPUT: "inDirPath" returns the full directory path to the given file.
% "inFileNamePrefixNoPath" returns the prefix portion of the name of the
% given file, i.e., the given name less the full directory path, index
% field, and file extension.
% "indFieldLength" returns the length of the index field of the given file.
% "inFileExt" returns the extension of the given file.
% "fileIndArr" returns a vector holding the indices of the found files.
%==========================================================================
function [inDirPath, inFileNamePrefixNoPath, indFieldLength, inFileExt, fileIndArr] = ...
    getFileSequenceFromRepresetative(inFileName, firstFileInd, lastFileInd)

if (nargin < 2)
    firstFileInd = uint64(0);
end
if (nargin < 3)
    lastFileInd = inf;
end

% Assert that the specified input file name is valid.
assert((isempty(inFileName) == false), 'SoundRestoration:getFileSequenceFromRepresetative:EmptyInputFileName', ...
        'Input file name is empty; it needs to be a non-empty string specifying an existing file.');
assert((ischar(inFileName) == true), 'SoundRestoration:getFileSequenceFromRepresetative:Not-A-StringInputFileName', ...
        'Input file name is not a string; it needs to be a non-empty string specifying an existing file.');
assert((exist(inFileName, 'file') == 2), 'SoundRestoration:getFileSequenceFromRepresetative:InexistingInputFile', ...
        'Input file %s does not exists.', inFileName);

% Find all dots in the given file name.
dotIndArr = regexp(inFileName, '\.');
% Determine the file extension and its length.
inFileExt = inFileName((dotIndArr(end) + 1):end);

% Find all directory separators in the given full directory path name
% (these are \ for Windows and / for Linux).
fileSepIndArr = regexp(inFileName, filesep);
% Determine the input directory (i.e., the directory where the given input
% file resides).
inDirPath = inFileName(1:fileSepIndArr(end));

% Find all non-digits before the last dot.
nonDigitIndArr = regexp(inFileName(1:(dotIndArr(end) - 1)), '[^0-9]');
% Determine the prefix without the full directory path.
inFileNamePrefixNoPath = inFileName((fileSepIndArr(end) + 1):nonDigitIndArr(end));
% Determine the length of the index field.
indFieldLength = dotIndArr(end) - nonDigitIndArr(end) - 1;
indFieldIndArr = (numel(inFileNamePrefixNoPath) + 1):(numel(inFileNamePrefixNoPath) + indFieldLength);
% Determine the length of the given file name excluding the directory path.
inFileNameNoPathLength = numel(inFileName) - fileSepIndArr(end);

% Find all files in the input directory and their number.
fileListing = dir(inDirPath);
numFiles = numel(fileListing);
% Allocate memory to store indices of the existing files.
fileIndArr = zeros(numFiles, 1, 'uint64');

% Find the indices of all files residing in the input directory that have
% the same prefix and extension as the given input file name.
numFoundFiles = 0;
for k = 1:numFiles
    
    % Get the current file name.
    currFileName = fileListing(k).name;
    
    % If the current file name matches the pattern of the given input file
    % name, then store the current file's index.
    [startInd, endInd] = regexpi(currFileName, ['^' inFileNamePrefixNoPath '[0-9]{' num2str(indFieldLength) '}\.' inFileExt '$']);
    if ( (isempty(startInd) == false)&&(isempty(endInd) == false)&&(startInd == 1)&&(endInd == inFileNameNoPathLength) )
        numFoundFiles = numFoundFiles + 1;
        fileIndArr(numFoundFiles) = sscanf(currFileName(indFieldIndArr),'%lu');
    end
end

% Trim off any unused entries.
fileIndArr = fileIndArr(1:numFoundFiles);
% Sort the found indices in ascending order.
fileIndArr = sort(fileIndArr);
% Keep only those that are within the specified allowed file indices.
fileIndArr = fileIndArr( (fileIndArr >= firstFileInd)&(fileIndArr <= lastFileInd) );

% Assert that there are no gaps in the file sequence.
assert((numel(fileIndArr) == (fileIndArr(end) - fileIndArr(1) + 1)), ...
    'SoundRestoration:GapsInFileSequence', ...
    'Gaps in the file sequence: first index is %d, last index is %d, all indices are %d.\n', ...
    fileIndArr(1), fileIndArr(end), numel(fileIndArr));

return;
% end of the function "getFileSequenceFromRepresetative"
